package com.cardone.platform.usercenter.service;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.utils.EntityUtils;
import com.cardone.persistent.CommonDtoAttributes;
import com.cardone.platform.usercenter.dao.OrgDao;
import com.cardone.platform.usercenter.dto.OrgDto;

/**
 * 部门服务
 * 
 * @author yaoht
 * 
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrgDefaultService implements OrgService {
	/**
	 * 部门数据持久
	 */
	private OrgDao orgDao;

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public int deleteOrgByCode(@NonNull OrgDto deleteOrg) {
		return this.orgDao.deleteByCode(deleteOrg, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public int deleteOrgByIds(@NonNull OrgDto deleteOrg) {
		return this.orgDao.deleteByIds(deleteOrg);
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<OrgDto> findListOrgByCode(@NonNull OrgDto findListOrg) {
		return this.orgDao.findListByCode(OrgDto.class, findListOrg, new String[] {}, new String[] {});
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<OrgDto> findListOrgByName(@NonNull OrgDto findListOrg) {
		return this.orgDao.findListByName(OrgDto.class, findListOrg);
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public OrgDto findOrgByCode(@NonNull OrgDto findOrg) {
		return this.orgDao.findByCode(OrgDto.class, findOrg, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public OrgDto findOrgById(@NonNull OrgDto findOrg) {
		return this.orgDao.findByCode(OrgDto.class, findOrg, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<OrgDto> paginationOrgByCode(@NonNull OrgDto paginationOrg) {
		return this.orgDao.paginationByCode(OrgDto.class, paginationOrg);
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<Map<String, Object>> paginationOrgByName(@NonNull OrgDto paginationOrg) {
		return this.orgDao.paginationByName(paginationOrg);
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readOrgByCodeNqId(@NonNull OrgDto readOrg) {
		return this.orgDao.readByCodeNqId(Integer.class, readOrg);
	}

	@Override
	@Cacheable(value = OrgService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readOrgByName(@NonNull OrgDto readOrg) {
		return this.orgDao.readByName(Integer.class, null, readOrg);
	}

	@Override
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public void reload() {
		this.orgDao.reload();
	}

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public OrgDto saveOrgByIdOrCode(@NonNull OrgDto saveOrg) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveOrg, CommonDtoAttributes.code.name());

		final OrgDto oldOrg = this.orgDao.findByCode(OrgDto.class, saveOrg, null, whereAndEqProperties);

		if (oldOrg == null) {
			saveOrg.setId(UUID.randomUUID().toString());

			this.orgDao.insertByCode(saveOrg);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveOrg);

			return this.orgDao.findByCode(OrgDto.class, saveOrg, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() }, saveOrg);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveOrg, oldOrg, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldOrg;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldOrg);

		com.cardone.common.utils.BeanUtils.copyProperties(oldOrg, saveOrg, notNullIdProperties);

		this.orgDao.updateByCode(saveOrg, updateProperties, notNullIdProperties);

		return this.orgDao.findByCode(OrgDto.class, oldOrg, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public OrgDto saveOrgByName(@NonNull OrgDto saveOrg) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveOrg, CommonDtoAttributes.code.name());

		final OrgDto oldOrg = this.orgDao.findByCode(OrgDto.class, saveOrg, null, whereAndEqProperties);

		if (oldOrg == null) {
			saveOrg.setId(UUID.randomUUID().toString());

			this.orgDao.insertByCode(saveOrg);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveOrg);

			return this.orgDao.findByCode(OrgDto.class, saveOrg, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() }, saveOrg);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveOrg, oldOrg, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldOrg;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldOrg);

		com.cardone.common.utils.BeanUtils.copyProperties(oldOrg, saveOrg, notNullIdProperties);

		this.orgDao.updateByCode(saveOrg, updateProperties, notNullIdProperties);

		return this.orgDao.findByCode(OrgDto.class, oldOrg, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public int updateOrgByCode(@NonNull OrgDto updateOrg) {
		return this.orgDao.updateByCode(updateOrg, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = OrgService.BEAN_ID, allEntries = true)
	public int updateOrgByIds(@NonNull OrgDto updateOrg) {
		return this.orgDao.updateByIds(updateOrg);
	}
}